using System;
using System.Collections.Generic;
using System.Text;
using System.Collections.ObjectModel;

namespace LispInterpretor.HelperClasses
{
    internal sealed class ParserHelper
    {
        internal static string ParseArguments(string text, int index)
        {
            IList<string> arguments = ParseArguments(text);

            return arguments[index];
        }

        internal static IList<string> ParseArguments(string text)
        {
            Collection<string> parsedFragements = new Collection<string>();

            int expressionDepth = 0;
            StringBuilder parsedFragement = new StringBuilder();

            foreach (char item in text)
            {
                if (item == '(')
                {
                    expressionDepth++;
                }

                bool firstLevelParen = (item == '(' || item == ')') && expressionDepth == 1;

                if (item == ')')
                {
                    expressionDepth--;
                }

                if (item == ' ' && expressionDepth == 1)
                {
                    parsedFragements.Add(parsedFragement.ToString());
                    parsedFragement = new StringBuilder();
                }
                else if(!firstLevelParen)
                {
                    parsedFragement.Append(item);
                }

            }

            string finalParsedItem = parsedFragement.ToString();

            if (!string.IsNullOrEmpty(finalParsedItem))
                parsedFragements.Add(finalParsedItem);

            return parsedFragements;
        }

        internal static string ParseFuncName(string text)
        {
            IList<string> parsedString = ParseArguments(text);

            Check.IsTrue(parsedString.Count > 0, "No function name found.");
            Check.IsTrue(text.StartsWith("("), "This doesn't appear to be a function application.");
            return parsedString[0];
        }

        internal static string ClearWhiteSpace(string text)
        {
            string allInSpaces = ConvertAllWhiteSpaceToSpaces(text);
            string doubleSpaceCleared = RemoveDoubleSpaces(allInSpaces);

            string rightHandParensSimplified = doubleSpaceCleared.Replace(") )", "))");
            string leftHandParensSimplified = rightHandParensSimplified.Replace("( (", "((");

            return leftHandParensSimplified;
        }

        private static string RemoveDoubleSpaces(string allInSpaces)
        {
            StringBuilder builder = new StringBuilder();

            bool lastCharacterWasSpace = false;

            foreach(char character in allInSpaces)
            {
                if (character == ' ')
                {
                    if (!lastCharacterWasSpace)
                    {
                        builder.Append(character);
                    }

                    lastCharacterWasSpace = true;
                }
                else
                {
                    lastCharacterWasSpace = false;
                    builder.Append(character);
                }
            }

            return builder.ToString();
        }

        private static string ConvertAllWhiteSpaceToSpaces(string text)
        {
            StringBuilder builder = new StringBuilder();

            foreach (char character in text)
            {
                if (Is(character, '\t', '\r', '\n'))
                {
                    builder.Append(' ');
                }
                else
                {
                    builder.Append(character);
                }
            }

            return builder.ToString();
        }

        private static bool Is(char character, params char[] items)
        {
            foreach (char item in items)
            {
                if (character == item)
                {
                    return true;
                }
            }

            return false;
        }
    }
}
